<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>面向对象</title>
</head>
<body>
  <script>
    /*
    * 构造函数实现继承
    */
    function Preson () {
      this.name = 'preson'
    }

    function Child () {
      Preson.call(this); // apply
      this.type = 'oop'
    }
    console.log(new Child)

    /**
     * 
     * 原型链继承
    */
   function Preson2 () {
     this.name = 'preson2'
     this.play = [1,2,3]
   }
   function Child2() {
     this.type = 'child2'
   }
   Child2.prototype = new Preson2()
   const c1 = new Child2
   const c2 = new Child2
   console.log(c1.play, c2.play); // 都是 123,123
   c1.play.push(4)
   console.log(c1.play, c2.play); // 都是 1234
  //  上面就是原型链继承的缺点 原型链继承生成的实例的 __proto__ 都是引用了同一个对象,所以只要一个实例修改了这个对象,其他实例所引用的这个对象也会被修改

  /**
   * 组合继承
  */
   function Preson3() {
     this.name = 'preson3'
     this.play = [1,2,3]
   }
   function Child3() {
     this.type = 'child3'
     Preson3.call(this); // 第一次执行 Preson3 构造函数
   }
   Child3.prototype = new Preson3() // 第二次执行 Preson3 构造函数
   const c3 = new Child3
   const c4 = new Child3
   c3.play.push(5)
   console.log(c3.play, c4.play) // 1235, 123
  // 组合继承方式使用 构造函数继承和原型链继承的两种方式 
  // 优点是解决了 原型继承和构造函数继承的缺点
  // 但是缺点却是执行了两次父类构造函数

  /**
   * 组合继承优化 1
  */

  function Preson4() {
    this.name = 'preson4'
  }
  function Child4() {
    this.type = 'child4'
    Preson4.call(this)
  }
  Child4.prototype = Preson4.prototype
  const c5 = new Child4
  console.log(c5 instanceof Child4) // true
  console.log(c5 instanceof Preson4)// true
  console.log(c5.constructor) // Preson 这里指向了 c5 父类的 父类 是不对的  c5 的父类应该是 Child4


  /**
   * 组合继承优化 最佳
  */

  function Preson5() {
    this.name = 'preson5'
  }
  function Child5() {
    this.type = 'preson5'
    Preson5.call(this)
  }
  // 使用 Object.create() 在父类和子类之间创建了一个新的对象 原型链的查找过程会是 子类 -> 中间对象 -> 父类
  Child5.prototype = Object.create(Preson5.prototype);
  Child5.prototype.constructor = Child5
  const c6 = new Child5
  console.log(c6 instanceof Child5) // true
  console.log(c6 instanceof Preson5) // true
  console.log(c6.constructor) // Child5
  </script>
</body>
</html>